<template>
  <!-- 使用外层容器避免 <dialog> 内嵌 <dialog> 导致层级与关闭行为异常 -->
  <div class="quote-dialog-wrapper">
    <dialog ref="dialogRef" class="quote-dialog" @close="onCloseInternal" @keydown="onDialogKeydown">
    <form method="dialog" class="dialog-body" @submit.prevent>
      <header class="mini-header">
        <h3 class="title with-icon"><span class="dlg-icon">
          <svg viewBox="0 0 24 24" stroke="currentColor" fill="none"><path d="M5 4h9l5 5v11a0 0 0 0 1 0 0H5a0 0 0 0 1 0 0V4Z" stroke-width="1.6"/><path d="M14 4v6h6" stroke-width="1.6"/><path d="M8 14h8M8 10h4M8 18h5" stroke-width="1.6" stroke-linecap="round"/></svg>
        </span>报价预览</h3>
        <div class="head-tools">
          <button type="button" class="btn ghost sm" @click="openPoster" :disabled="!product">报价</button>
          <button type="button" class="ui-close-btn" @click="close" aria-label="关闭">
            <svg class="icon-x" viewBox="0 0 24 24" fill="none"><line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" /></svg>
          </button>
        </div>
      </header>
  <section class="content" v-if="product">
        <div class="layout">
          <aside class="left-col">
            <section class="panel product-info">
              <h4>产品信息</h4>
              <ul class="kv">
                <li><span>编码</span><strong>{{ product.code }}</strong></li>
                <li><span>分类</span><strong>{{ product.category }}</strong></li>
                <li><span>状态</span><strong>{{ product.status==='pending' ? '待维护' : '已完成' }}</strong></li>
              </ul>
              <div v-if="product.mainImageUrl" class="p-img"><img :src="product.mainImageUrl" :alt="product.name" /></div>
            </section>
            <section class="panel attr-summary">
              <h4>关键属性</h4>
              <div v-if="encodingLoading" class="muted" style="padding:.4rem .2rem;">属性加载中...</div>
              <div v-else-if="attrEntries.length" class="attr-grid enhanced">
                <div v-for="kv in attrEntries" :key="kv.k" class="attr-chip" :class="[kv.from==='encoding'?'dyn':'loc']" :title="kv.vFull">
                  <span class="k">{{ kv.k }}<span v-if="kv.from==='encoding'" class="src-badge" aria-label="动态属性">D</span></span>
                  <span class="v">{{ kv.v }}</span>
                </div>
              </div>
              <p v-else class="muted">{{ encodingError || '暂无属性' }}</p>
            </section>
            <!-- 计算参数区域已移除 -->
          </aside>
          <main class="right-col">
            <section class="panel bom-detail" v-if="bom.length">
              <h4>BOM 明细</h4>
              <div class="bom-scroll-wrap">
              <table class="bom-detail-table">
                <thead>
                  <tr>
                    <th style="width:42px">#</th>
                    <th>物料</th>
                    <th>名称</th>
                    <th>编码</th>
                    <th>规格</th>
                    <th>单价✖️数量</th>
                    <th>价格({{ currency }})</th>
                  </tr>
                </thead>
                <tbody>
                  <tr v-for="(r,idx) in bomDisplay" :key="r.id">
                    <td>{{ idx+1 }}</td>
                    <td>{{ r.category || '-' }}</td>
                    <td>{{ r.displayName }}</td>
                    <td>{{ r.materialCode || '-' }}</td>
                    <td>{{ r.spec || '-' }}</td>
                    <td>{{ r.quantityDisplay }}</td>
                    <td>{{ r.priceDisplay }}</td>
                  </tr>
                </tbody>
                <tfoot>
                  <tr class="subtotal">
                    <td colspan="5" style="text-align:right;font-weight:600;">物料合计</td>
                    <td colspan="1"></td>
                    <td style="font-weight:600;">{{ bomTotal.toFixed(2) }}</td>
                  </tr>
                </tfoot>
              </table>
              </div>
            </section>
            <section class="panel extra-fees">
              <h4>非物料成本</h4>
              <div class="fees-grid readonly">
                <div class="fee-item"><label>港杂费</label><div class="fee-val">{{ harborFee.toFixed(2) }}</div></div>
                <div class="fee-item"><label>裁切费用</label><div class="fee-val">{{ cuttingFee.toFixed(2) }}</div></div>
                <div class="fee-item"><label>人工制造费用</label><div class="fee-val">{{ laborManufactureFee.toFixed(2) }}</div></div>
              </div>
              <div class="fee-summary"><span>非物料小计</span><strong>{{ extraFeesTotal.toFixed(2) }}</strong></div>
            </section>
            <section class="panel package-cost">
              <PackageCostSelector ref="packageSelectorRef" @cost-change="onPackageCostChange" @view-bom="viewPackageBom" />
            </section>
          </main>
        </div>
      </section>
      <footer class="mini-actions">
        <div class="final-pill" v-if="product">最终报价: <strong>{{ finalPrice.toFixed(2) }} {{ currency }}</strong></div>
        <button class="btn" type="button" @click="close">关闭</button>
      </footer>
    </form>
      <!-- BOM 查看对话框（保持在报价预览内部，不影响独立弹窗层级） -->
      <BomViewDialog ref="bomViewDialogRef" />
    </dialog>
  </div>
</template>
<script setup lang="ts">
import { ref, computed, nextTick } from 'vue';
import { useSkuStore, BomItemMock, SkuProductBase } from '../../../store/sku';
import { fetchSkuEncodingDetail } from '../../../services/sku';
import { useUnifiedAttributes } from '../../../composables/useUnifiedAttributes';
import PackageCostSelector from './PackageCostSelector.vue';
import BomViewDialog from '../../bomSimple/components/BomViewDialog.vue';
const dialogRef = ref<HTMLDialogElement|null>(null);
const skuCode = ref('');
const skuStore = useSkuStore();
const currency = 'CNY';
// 包装成本选择器引用
const packageSelectorRef = ref<InstanceType<typeof PackageCostSelector>|null>(null);
// BOM 查看对话框引用
const bomViewDialogRef = ref<InstanceType<typeof BomViewDialog>|null>(null);
const product = computed<SkuProductBase | undefined>(() => skuCode.value ? skuStore.getProduct(skuCode.value) : undefined);
const bom = computed<BomItemMock[]>(() => skuCode.value ? skuStore.getBom(skuCode.value) : []);
// 编码平台动态详情
const encodingDetail = ref<Record<string, any>|null>(null);
const encodingLoading = ref(false);
const encodingError = ref('');
// BOM 明细行展示格式
interface BomDisplayRow extends BomItemMock { displayName: string; quantityDisplay: string; priceDisplay: string; lineTotal: number; }
const bomDisplay = computed<BomDisplayRow[]>(()=> {
  return bom.value.map(row => {
    const fd = row.feeDetail;
    let quantityDisplay = '';
    let priceDisplay = '';
    let lineTotal = 0;
    if (fd) {
      if (fd.mode === 'fixed') {
        quantityDisplay = '/';
        priceDisplay = (fd.amount || 0).toFixed(2);
        lineTotal = fd.amount || 0;
      } else { // count
        const qty = fd.quantity ?? row.qty;
        const unitPrice = fd.amount || 0;
        quantityDisplay = `${unitPrice.toFixed(2)} ✖️ ${qty}`;
        lineTotal = unitPrice * qty;
        priceDisplay = lineTotal.toFixed(2);
      }
    } else {
      // fallback 使用 unitCost * qty
      lineTotal = (row.unitCost || 0) * row.qty;
      quantityDisplay = `${(row.unitCost||0).toFixed(2)} ✖️ ${row.qty}`;
      priceDisplay = lineTotal.toFixed(2);
    }
    return { ...row, displayName: row.costName || row.materialName, quantityDisplay, priceDisplay, lineTotal };
  });
});
const bomTotal = computed(()=> bomDisplay.value.reduce((s,r)=> {
  const val = typeof r.lineTotal === 'number' && !isNaN(r.lineTotal) ? r.lineTotal : 0;
  return s + val;
}, 0));

// 非物料成本（只读来自 store）
const extraFees = computed(()=> skuCode.value ? skuStore.getExtraFees(skuCode.value) : { harbor:0, cutting:0, labor:0 });
const harborFee = computed(()=> extraFees.value.harbor);
const cuttingFee = computed(()=> extraFees.value.cutting);
const laborManufactureFee = computed(()=> extraFees.value.labor);
const extraFeesTotal = computed(()=> {
  const hf = typeof harborFee.value === 'number' && !isNaN(harborFee.value) ? harborFee.value : 0;
  const cf = typeof cuttingFee.value === 'number' && !isNaN(cuttingFee.value) ? cuttingFee.value : 0;
  const lf = typeof laborManufactureFee.value === 'number' && !isNaN(laborManufactureFee.value) ? laborManufactureFee.value : 0;
  return hf + cf + lf;
});

// 包装成本
const packageCost = computed(() => skuCode.value ? skuStore.getPackageCost(skuCode.value) : { packageId: '', packageName: '', packageCode: '', cost: 0 });
const packageCostAmount = computed(() => {
  const cost = packageCost.value.cost;
  return typeof cost === 'number' && !isNaN(cost) ? cost : 0;
});

// 最终报价 = BOM合计 + 非物料合计 + 包装成本
const finalPrice = computed(()=> {
  const bt = typeof bomTotal.value === 'number' && !isNaN(bomTotal.value) ? bomTotal.value : 0;
  const et = typeof extraFeesTotal.value === 'number' && !isNaN(extraFeesTotal.value) ? extraFeesTotal.value : 0;
  const pc = typeof packageCostAmount.value === 'number' && !isNaN(packageCostAmount.value) ? packageCostAmount.value : 0;
  return bt + et + pc;
});

// 统一属性（含编码平台覆盖），去除数量限制以保持与“产品属性”弹窗一致；包含品名、编码。来源标记：encoding/local
const { unified: unifiedAttrs } = useUnifiedAttributes({ productRef: product as any, encodingDetailRef: encodingDetail, includeBaseFields: true });
// 过滤掉包含英文字母的属性键（仅保留中文或混合但不纯英文的键）
const attrEntries = computed(()=> unifiedAttrs.value
  .filter(a => /[a-zA-Z]/.test(a.key) ? /[\u4e00-\u9fa5]/.test(a.key) : true)
  .map(a=> ({ k: a.key, v: a.value, vFull: a.value, from: a.from })));

function recalc(){ /* 已不需要复杂计算，保留接口以便扩展 */ }
// 已彻底移除旧的 buildPdfInnerHtml 与 PDF 导出逻辑
function resetPreviewState(){ /* 占位：若将来需要状态复位可在此扩展 */ }

// 包装成本变化处理
function onPackageCostChange(packageInfo: { packageId: string; packageName: string; packageCode: string; cost: number }) {
  if (skuCode.value) {
    skuStore.setPackageCost(skuCode.value, packageInfo);
  }
}
// PDF 导出功能已移除：openPdfPreview 与 closePdfPreview 删除


// 预览组件内部不自动刷新；若需要实时刷新，可扩展传 reactive html

// 已移除旧 PDF 导出组件（PdfExportPreview），此行仅说明历史变更，可后续删除

async function open(row: { code:string }) {
  // 打开前确保预览状态复位，避免上次 ESC 关闭对话框但未重置 preview.
  resetPreviewState();
  skuCode.value=row.code;
  encodingDetail.value = null;
  encodingError.value = '';
  // 重置包装选择器
  if (packageSelectorRef.value) {
    packageSelectorRef.value.selectedPackageId = '';
  }
  const el=dialogRef.value; if(el){ el.showModal(); }
  if(row.code){
    encodingLoading.value = true;
    try {
      const detail = await fetchSkuEncodingDetail(row.code);
      encodingDetail.value = detail || {};
      // 为保持与 AttributeDialog 展示一致：将编码平台返回字段映射为统一的中文属性键并写入产品本地 attributes（不破坏原有键）
      const mappedAttrs: Record<string, any> = {
        客户简称: detail?.cusShortName || '',
        模具: detail?.mould || '',
        尺寸: detail?.buildingSize || detail?.innerSizeMm || '',
        材质: detail?.materialQuality || '',
        功能: detail?.productFun || '',
        形状: detail?.buildingFinishedShape || '',
        类别: detail?.productCategories || ''
      };
      const prod = skuStore.getProduct(row.code);
      if (prod) {
        // 若后端返回 materialName，更新产品名称（与 AttributeDialog 行为保持一致）
        if (detail?.materialName && typeof detail.materialName === 'string' && detail.materialName.trim()) {
          prod.name = detail.materialName.trim();
        }
        // 合并属性：已有属性优先，mappedAttrs 追加覆盖空值
        prod.attributes = { ...prod.attributes, ...Object.fromEntries(Object.entries(mappedAttrs).filter(([_,v]) => v !== '')) };
      }
    } catch(e:any){
      console.error('获取编码平台详情失败', e);
      encodingError.value = e?.message || '获取编码平台详情失败';
    } finally {
      encodingLoading.value = false;
    }
  }
}
function close(){ const el=dialogRef.value; if(el) el.close(); }
function onCloseInternal(){ skuCode.value=''; resetPreviewState(); encodingDetail.value=null; encodingError.value=''; }

function onDialogKeydown(e: KeyboardEvent){ /* 保留扩展 */ }
function openPoster(){ 
  if(!product.value) return; 
  // 在新标签页中打开报价海报
  const posterUrl = `/quote-poster/${product.value.code}`;
  window.open(posterUrl, '_blank');
}
// 打开包装BOM明细查看对话框
function viewPackageBom(pkg: any) {
  if (!pkg) {
    alert('包装方式信息获取失败');
    return;
  }
  // 将后端格式转换为 BomViewDialog 需要的格式
  const bomItems = convertBomSToItems(pkg.bomS || []);
  bomViewDialogRef.value?.open({ 
    title: '包装BOM明细 - ' + pkg.name, 
    bomItems: bomItems, 
    group: false 
  });
}
// 将后端 bomS 格式转换为 BomViewDialog 需要的格式
function convertBomSToItems(bomS: any[]): BomItemMock[] {
  return (bomS || []).map((item, idx) => {
    const bom = item.bom || {};
    const quantity = item.quantity ?? 1;
    
    // 将属性数组转换为对象和定义
    const attributeValues: Record<string, any> = {};
    const attributeDefinitions: any[] = [];
    if (Array.isArray(bom.attributes)) {
      bom.attributes.forEach((attr: any) => {
        attributeValues[attr.propertyName] = attr.propertyValue;
        attributeDefinitions.push({
          code: attr.propertyName,
          name: attr.propertyName,
          control: 'TextBox',
          sort: typeof attr.sort === 'number' ? attr.sort : undefined,
          propertyName: attr.propertyName
        });
      });
    }
    
    // 确定费用模式
    const feeMode = bom.feeModel === 'count' ? 'count' : 'fixed';
    
    return {
      id: bom.id || '',
      type: bom.bomType === 'package' ? 'packaging' : 'production',
      seq: idx + 1,
      materialCode: bom.invCode || '',
      materialName: bom.name || '',
      costName: bom.name || '',
      category: bom.className || '',
      spec: '',
      qty: quantity,
      unit: 'pcs',
      lossFactor: 1,
      unitCost: 0,
      attributes: attributeValues,
      feeDetail: {
        mode: feeMode,
        amount: bom.feeAmount || 0,
        quantity: feeMode === 'count' ? quantity : undefined,
        currency: 'CNY'
      }
    } as BomItemMock;
  });
}
defineExpose({ open });
</script>
<style scoped>
.quote-dialog-wrapper { position:relative; }
.quote-dialog::backdrop { background:rgba(0,0,0,.45); }
.quote-dialog { border:none; padding:0; border-radius:20px; width:1060px; max-width:96vw; box-shadow:0 18px 44px -12px rgba(0,0,0,.35),0 6px 18px -6px rgba(0,0,0,.2); }
.dialog-body { display:flex; flex-direction:column; max-height:78dvh; background:#fff; }
.mini-header { display:flex; justify-content:space-between; align-items:center; padding:.9rem 1.2rem; border-bottom:1px solid #e2e8f0; }
.title { margin:0; font-size:19px; font-weight:600; letter-spacing:.5px; display:flex; align-items:center; gap:.6rem; }
.title.with-icon .dlg-icon { width:26px; height:26px; color:#1d4ed8; background:#eff6ff; border:1px solid #bfdbfe; display:inline-flex; align-items:center; justify-content:center; border-radius:8px; box-shadow:0 0 0 1px #ffffff inset; }
.title.with-icon .dlg-icon svg { width:18px; height:18px; }
.head-tools { display:flex; align-items:center; gap:.6rem; }
.content { padding:0; overflow:auto; }
.layout { display:flex; align-items:stretch; }
.left-col { width:300px; flex:0 0 300px; display:flex; flex-direction:column; gap:1rem; padding:1rem 1rem 1.2rem; background:linear-gradient(180deg,#f8fafc,#ffffff); border-right:1px solid #e2e8f0; }
.right-col { flex:1; display:flex; flex-direction:column; gap:1.1rem; padding:1rem 1.1rem 1.4rem; }
.panel { background:#fff; border:1px solid #e2e8f0; border-radius:16px; padding:.9rem .95rem 1rem; display:flex; flex-direction:column; gap:.7rem; box-shadow:0 4px 16px -6px rgba(15,23,42,.15),0 2px 8px -4px rgba(15,23,42,.08); }
.panel h4 { margin:0; font-size:14px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; color:#475569; position:relative; padding-left:10px; }
.panel h4::before { content:""; position:absolute; left:0; top:50%; transform:translateY(-50%); width:4px; height:60%; border-radius:2px; background:linear-gradient(180deg,#3b82f6,#1e3a8a); box-shadow:0 0 0 1px rgba(30,58,138,.15); }
.panel.bom-detail h4::before { background:linear-gradient(180deg,#0ea5e9,#0369a1); }
.panel.extra-fees h4::before { background:linear-gradient(180deg,#10b981,#047857); }
.panel.package-cost h4::before { background:linear-gradient(180deg,#f59e0b,#d97706); }
.panel.product-info h4::before { background:linear-gradient(180deg,#6366f1,#4338ca); }
.panel.attr-summary h4::before { background:linear-gradient(180deg,#f59e0b,#d97706); }
.kv { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:.45rem; font-size:12px; }
.kv li { display:flex; justify-content:space-between; gap:.6rem; }
.kv span { color:#64748b; }
.p-img { margin-top:.4rem; text-align:center; }
.p-img img { max-width:100%; border-radius:12px; border:1px solid #e2e8f0; }
.attr-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(110px,1fr)); gap:.5rem; }
.attr-chip { border:1px solid #cbd5e1; border-radius:10px; padding:.35rem .45rem; background:#f8fafc; display:flex; flex-direction:column; gap:.2rem; min-height:52px; }
.attr-chip .k { font-size:11px; color:#64748b; font-weight:600; }
.attr-chip .v { font-size:12px; font-weight:600; color:#0f172a; word-break:break-all; }
/* 增强属性展示样式 */
.attr-grid.enhanced { grid-template-columns:repeat(auto-fill,minmax(130px,1fr)); }
.attr-chip.dyn { background:#eff6ff; border-color:#93c5fd; box-shadow:0 2px 6px -2px rgba(59,130,246,.25); }
.attr-chip.loc { background:#f8fafc; }
.attr-chip .src-badge { display:inline-block; margin-left:4px; background:#2563eb; color:#fff; font-size:10px; line-height:1; padding:2px 5px 3px; border-radius:8px; letter-spacing:.05em; font-weight:600; box-shadow:0 2px 4px -2px rgba(15,23,42,.35); }
.bom-detail-table { width:100%; border-collapse:separate; border-spacing:0; font-size:12px; }
.bom-scroll-wrap { max-height:340px; overflow:auto; border:1px solid #e2e8f0; border-radius:12px; background:#f8fafc; position:relative; }
.bom-scroll-wrap::-webkit-scrollbar { width:10px; }
.bom-scroll-wrap::-webkit-scrollbar-track { background:transparent; }
.bom-scroll-wrap::-webkit-scrollbar-thumb { background:#cbd5e1; border-radius:6px; }
.bom-scroll-wrap::-webkit-scrollbar-thumb:hover { background:#94a3b8; }
.bom-scroll-wrap thead { display:table-header-group; }
.bom-scroll-wrap thead th { position:sticky; top:0; z-index:10; box-shadow:inset 0 1px 0 0 rgba(255,255,255,.5), 0 2px 6px -1px rgba(0,0,0,.12); background:linear-gradient(180deg,#f1f5f9,#e9eef5) !important; margin:0; padding:.45rem .55rem; }
.bom-detail-table th, .bom-detail-table td { padding:.45rem .55rem; border-bottom:1px solid #f1f5f9; text-align:left; }
.bom-detail-table thead th { background:linear-gradient(180deg,#f1f5f9,#e9eef5); font-size:11px; letter-spacing:.05em; text-transform:uppercase; color:#475569; }
.bom-detail-table tfoot tr.subtotal td { background:#f1f5f9; }
.bom-detail-table tbody tr { transition:background .18s; }
.bom-detail-table tbody tr:nth-child(odd) { background:#fcfdff; }
.bom-detail-table tbody tr:hover { background:#eef6ff; }
.bom-detail-table td { vertical-align:middle; }
.bom-detail-table td:nth-child(3) { font-weight:600; color:#0f172a; }
.bom-detail-table td:last-child { font-weight:600; color:#1e3a8a; }
.bom-detail-table tfoot td { font-size:13px; }
.extra-fees .fees-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); gap:.6rem; }
.extra-fees .fee-item { display:flex; flex-direction:column; gap:.25rem; }
.extra-fees label { font-size:12px; font-weight:600; color:#334155; }
.extra-fees input { border:1px solid #cbd5e1; border-radius:8px; padding:.35rem .55rem; font-size:13px; background:#fff; transition:box-shadow .18s,border-color .18s; }
.extra-fees input:focus { outline:none; border-color:#3b82f6; box-shadow:0 0 0 3px rgba(59,130,246,.35); }
.extra-fees .fees-grid.readonly .fee-val { border:1px solid #e2e8f0; background:#f1f5f9; padding:.4rem .6rem; border-radius:8px; font-size:13px; font-weight:600; color:#0f172a; }
.fee-summary { display:flex; justify-content:space-between; align-items:center; font-size:13px; padding:.4rem .6rem; background:#f8fafc; border:1px solid #e2e8f0; border-radius:10px; }
.mini-actions { display:flex; justify-content:flex-end; gap:.9rem; align-items:center; padding:.65rem 1.1rem .85rem; border-top:1px solid #e2e8f0; background:#fff; }
.final-pill { font-size:13px; background:linear-gradient(135deg,#1e3a8a,#1e293b 55%,#0f172a); color:#fff; padding:.55rem 1.1rem; border-radius:999px; letter-spacing:.03em; box-shadow:0 4px 10px -4px rgba(0,0,0,.45); position:relative; overflow:hidden; }
.final-pill::after { content:''; position:absolute; inset:0; background:radial-gradient(circle at 25% 20%,rgba(255,255,255,.18),transparent 60%); mix-blend-mode:overlay; }
.empty { margin:0; color:#64748b; font-size:14px; text-align:center; padding:1.5rem 0; }
.btn { cursor:pointer; border:1px solid #2563eb; background:#3b82f6; color:#fff; padding:.55rem 1rem; border-radius:10px; font-size:13px; font-weight:600; display:inline-flex; align-items:center; gap:.4rem; }
.btn.sm { padding:.4rem .8rem; font-size:12px; }
.btn.ghost { background:#fff; border:1px solid #3b82f6; color:#1d4ed8; }
.btn:hover { background:#2563eb; color:#fff; }
.btn.ghost:hover { background:#eff6ff; }
/* 旧 PdfExportPreview 样式已彻底移除 */

/* 移除旧 buildPdfInnerHtml 相关样式块 */

</style>
